package com.zhiche.wms.service.outbound.impl;

import com.baomidou.mybatisplus.mapper.EntityWrapper;
import com.baomidou.mybatisplus.mapper.Wrapper;
import com.baomidou.mybatisplus.plugins.Page;
import com.baomidou.mybatisplus.service.impl.ServiceImpl;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.zhiche.wms.core.supports.BaseException;
import com.zhiche.wms.core.supports.enums.TableStatusEnum;
import com.zhiche.wms.core.utils.SnowFlakeId;
import com.zhiche.wms.domain.mapper.base.StorehouseMapper;
import com.zhiche.wms.domain.mapper.log.CancelStoreLogMapper;
import com.zhiche.wms.domain.mapper.outbound.OutboundNoticeHeaderMapper;
import com.zhiche.wms.domain.mapper.outbound.OutboundShipHeaderMapper;
import com.zhiche.wms.domain.mapper.outbound.OutboundShipLineMapper;
import com.zhiche.wms.domain.model.base.StoreLocation;
import com.zhiche.wms.domain.model.base.Storehouse;
import com.zhiche.wms.domain.model.inbound.InboundPutawayHeader;
import com.zhiche.wms.domain.model.inbound.InboundPutawayLine;
import com.zhiche.wms.domain.model.log.CancelStoreLog;
import com.zhiche.wms.domain.model.movement.MovementHeader;
import com.zhiche.wms.domain.model.movement.MovementLine;
import com.zhiche.wms.domain.model.opbaas.StatusLog;
import com.zhiche.wms.domain.model.otm.OtmOrderRelease;
import com.zhiche.wms.domain.model.outbound.OutboundNoticeHeader;
import com.zhiche.wms.domain.model.outbound.OutboundNoticeLine;
import com.zhiche.wms.domain.model.outbound.OutboundShipHeader;
import com.zhiche.wms.domain.model.outbound.OutboundShipLine;
import com.zhiche.wms.domain.model.sys.User;
import com.zhiche.wms.dto.outbound.OutboundShipListDTO;
import com.zhiche.wms.dto.outbound.OutboundShipParamDTO;
import com.zhiche.wms.dto.outbound.OutboundShipQrCodeResultDTO;
import com.zhiche.wms.dto.outbound.OutboundShipQuitResultDTO;
import com.zhiche.wms.service.base.IBusinessDocNumberService;
import com.zhiche.wms.service.base.IStoreLocationService;
import com.zhiche.wms.service.constant.MovementType;
import com.zhiche.wms.service.constant.PutAwayType;
import com.zhiche.wms.service.constant.SourceSystem;
import com.zhiche.wms.service.inbound.IInboundPutawayHeaderService;
import com.zhiche.wms.service.movement.IMovementHeaderService;
import com.zhiche.wms.service.opbaas.IStatusLogService;
import com.zhiche.wms.service.otm.IOtmOrderReleaseService;
import com.zhiche.wms.service.outbound.*;
import com.zhiche.wms.service.sys.IUserService;
import com.zhiche.wms.service.utils.CommonMethod;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.*;

/**
 * <p>
 * 出库单头 服务实现类
 * </p>
 *
 * @author qichao
 * @since 2018-06-08
 */
@Service
public class OutboundShipHeaderServiceImpl extends ServiceImpl<OutboundShipHeaderMapper, OutboundShipHeader> implements IOutboundShipHeaderService {

    private static final Logger LOGGER = LoggerFactory.getLogger(OutboundShipHeaderServiceImpl.class);

    @Autowired
    private IOutboundNoticeHeaderService outboundNoticeHeaderService;
    @Autowired
    private IOutboundNoticeLineService outboundNoticeLineService;
    @Autowired
    private IBusinessDocNumberService businessDocNumberService;
    @Autowired
    private IMovementHeaderService movementHeaderService;
    @Autowired
    private IOutboundShipLineService outboundShipLineService;
    @Autowired
    private SnowFlakeId snowFlakeId;
    @Autowired
    private IOutboundPrepareHeaderService prepareHeaderService;
    @Autowired
    private IBusinessDocNumberService docNumberService;
    @Autowired
    private IStoreLocationService locationService;
    @Autowired
    private IUserService userService;
    @Autowired
    private IInboundPutawayHeaderService inboundPutawayHeaderService;
    @Autowired
    private IOtmOrderReleaseService releaseService;
    @Autowired
    private IStatusLogService statusLogService;
    @Autowired
    private CancelStoreLogMapper cancelStoreLogMapper;
    @Autowired
    private OutboundNoticeHeaderMapper outboundNoticeHeaderMapper;
    @Autowired
    private OutboundShipLineMapper outboundShipLineMapper;
    @Autowired
    private StorehouseMapper storehouseMapper;


    @Override
    public void setReleaseAndStatusLog(Long noticeLineId, OutboundNoticeLine outboundNoticeLine, User loginUser) {
        EntityWrapper<OtmOrderRelease> oorEW = new EntityWrapper<>();
        oorEW.eq("release_gid", outboundNoticeLine.getLineSourceKey())
                .eq("status", TableStatusEnum.STATUS_10.getCode());
        List<OtmOrderRelease> otmOrderReleases = releaseService.selectList(oorEW);
        if (CollectionUtils.isNotEmpty(otmOrderReleases)) {
            if (otmOrderReleases.size() > 1) {
                LOGGER.info("通知明细:{}存在多条ReleaseGid:", outboundNoticeLine.getLineSourceKey());
                throw new BaseException("车架号:" + otmOrderReleases.get(0).getVin() + "存在多条运单:" + outboundNoticeLine.getLineSourceKey());
            }
            OtmOrderRelease release = otmOrderReleases.get(0);
            OtmOrderRelease newRe = new OtmOrderRelease();
            //修改出库确认更新运单状态为出库 hgy 20200825
            release.setStatus(TableStatusEnum.STATUS_WMS_OUTBOUND.getCode());
            release.setId(release.getId());
            releaseService.updateById(release);
            StatusLog statusLog = new StatusLog();
            statusLog.setTableType(TableStatusEnum.STATUS_10.getCode());
            statusLog.setTableId(String.valueOf(release.getId()));
            statusLog.setStatus(TableStatusEnum.STATUS_WMS_OUTBOUND.getCode());
            statusLog.setStatusName(TableStatusEnum.STATUS_WMS_OUTBOUND.getCode());
            statusLog.setUserCreate(loginUser.getName());
            statusLogService.insert(statusLog);
        }
    }

    @Override
    public Page<OutboundShipListDTO> queryOutboundShipPage(Page<OutboundShipListDTO> page) {
        Wrapper<OutboundShipListDTO> wp = buildWrapper(page);
        List<OutboundShipListDTO> result = baseMapper.selectPageShipList(page, wp);
        page.setRecords(result);
        return page;
    }

    private Wrapper<OutboundShipListDTO> buildWrapper(Page<OutboundShipListDTO> page) {
        if (page == null) {
            throw new BaseException("参数不能为空");
        }
        Wrapper<OutboundShipListDTO> wp = new EntityWrapper<>();
        Map cd = page.getCondition();
        if (cd != null) {
            if (Objects.nonNull(cd.get("noticeHeadNo")) &&
                    StringUtils.isNotBlank(cd.get("noticeHeadNo").toString())) {
                wp.eq("noticeHeadNo", cd.get("noticeHeadNo").toString());
            }
            if (Objects.nonNull(cd.get("noticeHeadSourceNo")) &&
                    StringUtils.isNotBlank(cd.get("noticeHeadSourceNo").toString())) {
                wp.eq("noticeHeadSourceNo", cd.get("noticeHeadSourceNo").toString());
            }
            if (Objects.nonNull(cd.get("noticeLineStatus")) &&
                    StringUtils.isNotBlank(cd.get("noticeLineStatus").toString())) {
                wp.eq("noticeLineStatus", cd.get("noticeLineStatus").toString());
            } else {
                wp.ne("noticeLineStatus", TableStatusEnum.STATUS_50.getCode());
            }
            if (Objects.nonNull(cd.get("prepareStatus")) &&
                    StringUtils.isNotBlank(cd.get("prepareStatus").toString())) {
                wp.eq("prepareStatus", cd.get("prepareStatus").toString());
            }
            if (Objects.nonNull(cd.get("houseId")) &&
                    StringUtils.isNotBlank(cd.get("houseId").toString())) {
                wp.eq("houseId", cd.get("houseId"));
            }
            if (Objects.nonNull(cd.get("ownerOrderNo")) &&
                    StringUtils.isNotBlank(cd.get("ownerOrderNo").toString())) {
                wp.eq("owner_order_no", cd.get("ownerOrderNo").toString());
            }
            if (Objects.nonNull(cd.get("startDate")) && StringUtils.isNotEmpty((String) cd.get("startDate"))) {
                wp.ge("inbound_modified", cd.get("startDate").toString());
            }
            if (Objects.nonNull(cd.get("endDate")) && StringUtils.isNotEmpty((String) cd.get("endDate"))) {
                wp.le("inbound_modified", cd.get("endDate").toString());
            }
            if (Objects.nonNull(cd.get("lotNo1")) && StringUtils.isNotBlank(cd.get("lotNo1").toString())) {
                String vin = cd.get("lotNo1").toString();
                List<String> vins = Arrays.asList(CommonMethod.setVins(vin));
                wp.andNew().in("lot_no1", vins).or().like("lot_no1", vin);
            }
        }
        wp.orderBy("noticeHeadCreate", Boolean.FALSE).orderBy("noticeHeadId", Boolean.TRUE);
        return wp;
    }

    /**
     * 出库确认
     */
    @Override
    public ArrayList<String> updateOutboundShipConfirm (OutboundShipParamDTO dto) {
        if (dto == null) {
            throw new BaseException("参数不能为空");
        }
        String noticeLineIds = dto.getNoticeLineIds();
        if (StringUtils.isBlank(noticeLineIds)) {
            throw new BaseException("请选择出库确认的数据");
        }

        User loginUser = userService.getLoginUser();
        if (loginUser == null) {
            throw new BaseException("请登后进行该操作!");
        }

        String[] split = noticeLineIds.split(",");
        ArrayList<Long> ids = Lists.newArrayList();
        for (String str : split) {
            ids.add(Long.valueOf(str));
        }
        //出库确认生成出库单
        EntityWrapper<OutboundNoticeLine> lep = new EntityWrapper<>();
        lep.in("id", ids);
        List<OutboundNoticeLine> noticeLines = outboundNoticeLineService.selectList(lep);
        LOGGER.info("查询出库通知单是否存在 noticeLines.size : {}", noticeLines.size());
        if (CollectionUtils.isEmpty(noticeLines)) {
            throw new BaseException("未查询到noticeLineIds:" + noticeLineIds + "的通知单信息");
        }
        ArrayList<String> result = Lists.newArrayList();
        for (OutboundNoticeLine v : noticeLines) {
            StringBuilder sb = new StringBuilder();
            try {
                //调用方法出库
                outboundShipLineService.shipByNoticeLineId(v.getId(), PutAwayType.NOTICE_PUTAWAY, SourceSystem.HAND_MADE);
                //调用方法修改备料状态完成
                prepareHeaderService.updatePrepareFinishByLineId(v.getId(), loginUser.getName());
            } catch (BaseException e) {
                sb.append("车架号:").append(v.getLotNo1()).append(":").append(e.getMessage());
            } catch (Exception ex) {
                LOGGER.error("更改备料状态异常信息为{}",ex.getMessage());
                sb.append("车架号:").append(v.getLotNo1()).append(":系统异常");
            }
            if (StringUtils.isNotBlank(sb)) {
                result.add(sb.toString());
            }
        }
        return result;
    }

    /**
     * 查询扫码出库信息
     */
    @Override
    public OutboundShipQrCodeResultDTO getOutShipInfoByScan(OutboundShipParamDTO dto) {
        if (dto == null) {
            throw new BaseException("传入参数为空");
        }
        String houseId = dto.getHouseId();
        String lotNo1 = dto.getLotNo1();
        if (StringUtils.isBlank(houseId)) {
            throw new BaseException("仓库id为空");
        }
        if (StringUtils.isBlank(lotNo1)) {
            throw new BaseException("扫码信息不能为空");
        }
        //调整支持绑定二维码入库
        EntityWrapper<OtmOrderRelease> reEW = new EntityWrapper<>();
        reEW.eq("qr_code", lotNo1)
                .ne("status", TableStatusEnum.STATUS_50.getCode())
                .orderBy("id", false);
        OtmOrderRelease release = releaseService.selectOne(reEW);
        if (release != null) {
            lotNo1 = release.getVin();
        }
        //扫码查询通知单
        HashMap<String, Object> params = Maps.newHashMap();
        params.put("lotNo1", lotNo1);
        params.put("houseId", houseId);
        List<OutboundShipQrCodeResultDTO> list = outboundNoticeLineService.selectQrCodeInfoByParams(params);
        if (CollectionUtils.isEmpty(list)) {
            throw new BaseException("未查询到仓库id:" + houseId + "的lotNo1:" + lotNo1 + "的通知单信息");
        }
        if (list.size() > 1) {
            throw new BaseException("查询到仓库id:" + houseId + "的lotNo1:" + lotNo1 + "的多条通知单信息");
        }
        return list.get(0);
    }


    /**
     * 扫码出库确认
     */
    @Override
    public void updateOutShipConfirmScan(OutboundShipParamDTO dto) {
        User loginUser = userService.getLoginUser();
        if (loginUser == null) {
            throw new BaseException("请登后进行该操作!");
        }
        if (dto == null) {
            throw new BaseException("参数不能为空");
        }
        String noticeLineId = dto.getNoticeLineId();
        String houseId = dto.getHouseId();
        if (StringUtils.isBlank(houseId)) {
            throw new BaseException("请选择仓库后进行该操作");
        }
        if (StringUtils.isBlank(noticeLineId)) {
            throw new BaseException("出库LineId不能为空");
        }
        OutboundNoticeLine noticeLine = outboundNoticeLineService.selectById(Long.valueOf(noticeLineId));
        if (noticeLine == null) {
            throw new BaseException("未查询NotieLineId:" + noticeLineId + "通知单信息");
        }
        if (TableStatusEnum.STATUS_50.getCode().equals(noticeLine.getStatus())) {
            throw new BaseException("查询NotieLineId:" + noticeLineId + "已经通知取消不能进行出库");
        }
        if (TableStatusEnum.STATUS_30.getCode().equals(noticeLine.getStatus())) {
            throw new BaseException("查询NotieLineId:" + noticeLineId + "已经进行过出库操作");
        }
        //调用方法出库
        outboundShipLineService.shipByNoticeLineId(noticeLine.getId(), PutAwayType.NOTICE_PUTAWAY, SourceSystem.HAND_MADE);
        //调用方法修改备料状态
        prepareHeaderService.updatePrepareFinishByLineId(noticeLine.getId(), loginUser.getName());
    }

    /**
     * 获取退库车辆信息
     */
    @Override
    public OutboundShipQuitResultDTO getOutboundShipInfoForQuit (OutboundShipParamDTO dto) {
        if (dto == null) {
            throw new BaseException("参数不能为空");
        }
        String lotNo1 = dto.getLotNo1();
        String outShipLineId = dto.getOutShipLineId();
        String houseId = dto.getHouseId();
        if (StringUtils.isBlank(lotNo1)) {
            throw new BaseException("查询车辆架号为空");
        }
        if (StringUtils.isBlank(houseId)) {
            throw new BaseException("仓库信息为空");
        }
        if (StringUtils.isEmpty(outShipLineId)) {
            throw new BaseException("出库记录id【oslId】不能为空");
        }

        //扫码查询通知单
        HashMap<String, Object> params = Maps.newHashMap();
        params.put("outShipLineId", outShipLineId);
        params.put("lotNo1", lotNo1);
        params.put("houseId", houseId);
        List<OutboundShipQuitResultDTO> list = outboundShipLineService.selectQuitInfo(params);
        if (CollectionUtils.isEmpty(list)) {
            throw new BaseException("未查询到仓库id:" + houseId + "的lotNo1:" + lotNo1 + "的出库信息");
        }
        if (list.size() > 1) {
            throw new BaseException("查询到仓库id:" + houseId + "的lotNo1:" + lotNo1 + "的多次出库信息");
        }
        return list.get(0);
    }

    /**
     * 备料退库
     * 已出库数据做备料退库与扫码入库类似,可选择库位并打印库位
     */
    @Override
    public void updateOutboundShipQuit(OutboundShipParamDTO dto) {
        if (dto == null) {
            throw new BaseException("参数不能为空");
        }
        User loginUser = userService.getLoginUser();
        if (loginUser == null) {
            throw new BaseException("请先登录,再进行该操作");
        }
        String noticeLineId = dto.getNoticeLineId();
        String houseId = dto.getHouseId();
        String locationId = dto.getLocationId();
        if (StringUtils.isBlank(noticeLineId)) {
            throw new BaseException("请选择需要退库的数据");
        }
        if (StringUtils.isBlank(locationId)) {
            throw new BaseException("请选择存放库位");
        }
        if (StringUtils.isBlank(houseId)) {
            throw new BaseException("仓库id不能为空");
        }
        OutboundNoticeLine noticeLine = outboundNoticeLineService.selectById(noticeLineId);
        if (noticeLine == null) {
            throw new BaseException("未查询到出库通知单:" + noticeLineId + "的出库信息");
        }

        //查询是否有退库操作
        Wrapper<OutboundShipLine> oslEw = new EntityWrapper<>();
        oslEw.eq("notice_line_id", noticeLineId);
        oslEw.eq("is_quit", TableStatusEnum.STATUS_1.getCode());
        List<OutboundShipLine> outboundShipLines = outboundShipLineMapper.selectList(oslEw);
        if (CollectionUtils.isNotEmpty(outboundShipLines)) {
            throw new BaseException("车架号:【" + noticeLine.getLotNo1() + "】已有退库信息");
        }
        OutboundNoticeHeader nh = outboundNoticeHeaderService.selectById(noticeLine.getHeaderId());
        StoreLocation storeLocation = locationService.selectById(locationId);
        if (storeLocation == null) {
            throw new BaseException("未查询到存储库位locationId:" + locationId + "的信息");
        }
        InboundPutawayHeader iph = new InboundPutawayHeader();
        BeanUtils.copyProperties(nh, iph);
        iph.setId(snowFlakeId.nextId());
        // 通知单号  退库不存通知单id
        iph.setNoticeId(nh.getId());
        iph.setInboundNo(docNumberService.getInboundPutAwayNo());
        iph.setInboundTime(new Date());
        iph.setInboundSumQty(nh.getOutboundSumQty());
        iph.setLineCount(1);
        iph.setGenMethod(SourceSystem.HAND_MADE);
        iph.setType(TableStatusEnum.STATUS_50.getCode());
        iph.setLocationNo(storeLocation.getCode());
        iph.setStatus(TableStatusEnum.STATUS_10.getCode());
        iph.setUserCreate(loginUser.getName());
        iph.setUserModified(loginUser.getName());
        iph.setRemarks("退库");

        ArrayList<InboundPutawayLine> lines = Lists.newArrayList();
        InboundPutawayLine ipl = new InboundPutawayLine();
        BeanUtils.copyProperties(noticeLine, ipl);
        ipl.setId(snowFlakeId.nextId());
        ipl.setHeaderId(iph.getId());
        ipl.setNoticeLineId(noticeLine.getId());
        ipl.setLocationId(storeLocation.getId());
        ipl.setLocationNo(storeLocation.getCode());
        ipl.setInboundQty(noticeLine.getExpectQty());
        ipl.setGmtCreate(new Date());
        ipl.setRemarks("退库");
        lines.add(ipl);
        iph.setInboundPutawayLineList(lines);
        // 调用入库方法获取
        boolean result = inboundPutawayHeaderService.insertMovementByPutaway(iph, loginUser)
                && inboundPutawayHeaderService.savePutAway(iph);
        if (!result) {
            throw new BaseException("入库失败");
        }
        //退库记录
        this.saveRefundStoreLog(dto,loginUser.getName(),noticeLine,storeLocation.getId());

        //更新是否退库字段
        OutboundShipLine obslParam = new OutboundShipLine();
        obslParam.setGmtModified(new Date());
        obslParam.setIsQuit(TableStatusEnum.STATUS_1.getCode());
        Wrapper<OutboundShipLine> shipLineEw = new EntityWrapper<>();
        shipLineEw.eq("notice_line_id", noticeLineId);
        outboundShipLineMapper.update(obslParam,shipLineEw);
    }

    /**
     * 退库记录表
     * @param dto 前端入参
     * @param userName 登录用户
     * @param obnLine 出库详细记录
     * @param locationNo 库位编码
     */
    private void saveRefundStoreLog (OutboundShipParamDTO dto, String userName, OutboundNoticeLine obnLine, Long locationNo) {
        //1、通过noticeLineId查询line_source_key,通过lineSourceKey 查询otm_order_release
        Wrapper<OtmOrderRelease> otmEw = new EntityWrapper<>();
        otmEw.eq("release_gid", obnLine.getLineSourceKey());

        OutboundNoticeHeader params = new OutboundNoticeHeader();
        params.setId(obnLine.getHeaderId());
        OutboundNoticeHeader outNoticeHeaderResult = outboundNoticeHeaderMapper.selectOne(params);

        //2、退库记录表
        CancelStoreLog cancelStoreLog = new CancelStoreLog();
        cancelStoreLog.setVin(obnLine.getLotNo1());
        cancelStoreLog.setStatusOutbound(obnLine.getStatus());
        cancelStoreLog.setNoticeNo(outNoticeHeaderResult.getNoticeNo());
        cancelStoreLog.setOwnerOrderNo(obnLine.getOwnerOrderNo());
        cancelStoreLog.setHouseName(this.getHouseName(dto.getHouseId()));
        cancelStoreLog.setOutboundLineId(obnLine.getId());
        cancelStoreLog.setUserCancel(userName);
        cancelStoreLog.setGmtCreate(new Date());
        cancelStoreLog.setGmtModified(new Date());
        cancelStoreLog.setStoreHouseId(dto.getHouseId());
        cancelStoreLog.setOwnerId(obnLine.getOwnerId());
        cancelStoreLog.setLocationNo(String.valueOf(locationNo));
        HashMap<String,Object> queryParams = new HashMap<>();
        queryParams.put("lotNo1", cancelStoreLog.getVin());
        queryParams.put("houseId", cancelStoreLog.getStoreHouseId());
        List<OutboundShipQuitResultDTO> list = outboundShipLineService.selectQuitInfoByParams(queryParams);
        if(CollectionUtils.isNotEmpty(list)){
            cancelStoreLog.setStanVehicleType(list.get(0).getMaterielId());
            cancelStoreLog.setVehicleDescribe(list.get(0).getMaterielName());
        }
        OtmOrderRelease otmOrderRelease = releaseService.selectOne(otmEw);
        if (null != otmOrderRelease) {
            cancelStoreLog.setVin(otmOrderRelease.getVin());
            cancelStoreLog.setStanVehicleType(otmOrderRelease.getStanVehicleType());
            cancelStoreLog.setVehicleDescribe(otmOrderRelease.getVehicleDescribe());
        }
        if(StringUtils.isNotEmpty(dto.getRemark())){
            cancelStoreLog.setRemark(dto.getRemark());
        }
        this.cancelStoreLogMapper.insert(cancelStoreLog);
    }

    private String getHouseName (String houseId) {
        EntityWrapper<Storehouse> ew = new EntityWrapper<>();
        ew.eq("id",houseId);
        Storehouse storehouse = storehouseMapper.selectById(houseId);
        if(null != storehouse){
            return storehouse.getName();
        }
        return null;
    }


    @Override
    public boolean saveShip(OutboundShipHeader outboundShipHeader) {
        List<OutboundShipLine> outboundShipLines = outboundShipHeader.getOutboundShipLineList();
        if(CollectionUtils.isEmpty(outboundShipLines)){
            return false;
        }
        insert(outboundShipHeader);
        return insertoutboundShipLine(outboundShipLines);
    }

    private boolean insertoutboundShipLine (List<OutboundShipLine> outboundShipLines) {
        try {
            for (OutboundShipLine outboundShipLine : outboundShipLines) {
                outboundShipLineService.insert(outboundShipLine);
            }
            return true;
        } catch (Exception e) {
            LOGGER.error("插入出库记录明细异常{}", e.getMessage());
            return false;
        }
    }

    /**
     * 根据出库单插入移位单
     */
    @Override
    public boolean insertMovementByShip (OutboundShipHeader outboundShipHeader, User loginUser) {
        LOGGER.info("组装出库单插入移位单 {},操作用户 ：{}", outboundShipHeader.getId(), loginUser);
        //移位单头
        MovementHeader movementHeader = new MovementHeader();
        movementHeader.setMovementNo(businessDocNumberService.getMovementNo());
        movementHeader.setOwnerId(outboundShipHeader.getOwnerId());
        movementHeader.setStoreHouseId(outboundShipHeader.getStoreHouseId());
        movementHeader.setOrderDate(outboundShipHeader.getOutboundTime());
        movementHeader.setBusinessType(MovementType.OUTBOUND_MOVE);
        movementHeader.setUserCreate(loginUser.getName());
        movementHeader.setUserModified(loginUser.getName());
        movementHeader.setBusinessDocId(outboundShipHeader.getId());

        for (OutboundShipLine outboundShipLine : outboundShipHeader.getOutboundShipLineList()) {
            MovementLine movementLine = new MovementLine();
            BeanUtils.copyProperties(outboundShipLine, movementLine);
            movementLine.setHeaderId(movementHeader.getId());
            movementLine.setRelationLineId(outboundShipLine.getId());
            movementLine.setType(MovementType.LINE_OUT);
            movementLine.setSourceLocationId(outboundShipLine.getLocationId());
            movementLine.setQty(outboundShipLine.getOutboundQty());
            movementLine.setNetWeight(outboundShipLine.getOutboundNetWeight());
            movementLine.setGrossWeight(outboundShipLine.getOutboundGrossWeight());
            movementLine.setGrossCubage(outboundShipLine.getOutboundGrossCubage());
            movementLine.setPackedCount(outboundShipLine.getOutboundPackedCount());
            movementHeader.addMovementLine(movementLine);
        }
        //保存并审核移位单、入库单
        return movementHeaderService.createAndAuditMovenment(movementHeader);
    }
}
